package com.github.pavlospt;


import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Circle;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;

/**
 * CircleView
 *
 * @since 2021-06-15
 */
public class CircleView extends Component {

    private static final int NUM_2 = 2;
    private static final int NUM_10 = 10;
    private static final int NUM_25 = 25;
    private static final int NUM_360 = 360;
    private static final int NUM_30 = 30;
    private static final float NUM_5F = 0.5f;
    private static int DEFAULT_TITLE_COLOR = Color.CYAN.getValue();
    private static int DEFAULT_SUBTITLE_COLOR = Color.WHITE.getValue();
    private static String DEFAULT_TITLE = "title";
    private static String DEFAULT_SUBTITLE = "subtitle";

    private static boolean DEFAULT_SHOW_TITLE = true;
    private static boolean DEFAULT_SHOW_SUBTITLE = true;

    private static int DEFAULT_TITLE_SIZE = 25;
    private static int DEFAULT_SUBTITLE_SIZE = 20;
    private static float DEFAULT_TITLE_SUBTITLE_SPACE = 0f;

    private static int DEFAULT_STROKE_COLOR = Color.CYAN.getValue();
    private static int DEFAULT_BACKGROUND_COLOR = Color.WHITE.getValue();
    private static int DEFAULT_FILL_COLOR = Color.DKGRAY.getValue();

    private static float DEFAULT_STROKE_WIDTH = 5f;
    private static float DEFAULT_FILL_RADIUS = 0.9f;

    private static final int DEFAULT_VIEW_SIZE = 96;

    private int mTitleColor = DEFAULT_TITLE_COLOR;
    private int mSubtitleColor = DEFAULT_SUBTITLE_COLOR;
    private int mStrokeColor = DEFAULT_STROKE_COLOR;
    private int mBackgroundColor = DEFAULT_BACKGROUND_COLOR;
    private int mFillColor = DEFAULT_FILL_COLOR;
    private int weight;
    private int height;
    private String mTitleText = DEFAULT_TITLE;
    private String mSubtitleText = DEFAULT_SUBTITLE;

    private int mTitleSize = DEFAULT_TITLE_SIZE;
    private int mSubtitleSize = DEFAULT_SUBTITLE_SIZE;
    private float mStrokeWidth = DEFAULT_STROKE_WIDTH;
    private float mFillRadius = DEFAULT_FILL_RADIUS;
    private float mTitleSubtitleSpace = DEFAULT_TITLE_SUBTITLE_SPACE;

    private boolean mShowTitle = DEFAULT_SHOW_TITLE;
    private boolean mShowSubtitle = DEFAULT_SHOW_SUBTITLE;

    private Paint mTitleTextPaint;
    private Paint mSubTextPaint;

    private Paint mStrokePaint;
    private Paint mBackgroundPaint;
    private Paint mFillPaint;

    private RectFloat mInnerRectF;


    /**
     * CircleView
     *
     * @param context context
     */
    public CircleView(Context context) {
        super(context);
        init(null, 0);
    }

    /**
     * CircleView
     *
     * @param context context
     * @param attrs   attrs
     */
    public CircleView(Context context, AttrSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    /**
     * CircleView
     *
     * @param context   context
     * @param attrSet   attrSet
     * @param styleName styleName
     */
    public CircleView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(attrSet, 0);
    }

    /**
     * CircleView
     *
     * @param context context
     * @param attrSet attrSet
     * @param resId   resId
     */
    public CircleView(Context context, AttrSet attrSet, int resId) {
        super(context, attrSet, resId);
        init(attrSet, resId);
    }


    private void init(AttrSet attrs, int defStyle) {
        mTitleColor = AttrUtils.getColorFromAttr(attrs, "cv_titleColor", DEFAULT_TITLE_COLOR);
        mSubtitleColor = AttrUtils.getColorFromAttr(attrs, "cv_subtitleColor", DEFAULT_SUBTITLE_COLOR);
        mBackgroundColor = AttrUtils.getColorFromAttr(attrs, "cv_backgroundColorValue", DEFAULT_BACKGROUND_COLOR);
        mStrokeColor = AttrUtils.getColorFromAttr(attrs, "cv_strokeColorValue", DEFAULT_STROKE_COLOR);
        mFillColor = AttrUtils.getColorFromAttr(attrs, "cv_fillColor", DEFAULT_FILL_COLOR);
        mTitleSize = AttrUtils.getDimensionFromAttr(attrs, "cv_titleSize", DEFAULT_TITLE_SIZE);
        mSubtitleSize = AttrUtils.getDimensionFromAttr(attrs, "cv_subtitleSize", DEFAULT_SUBTITLE_SIZE);
        mStrokeWidth = AttrUtils.getFloatFromAttr(attrs, "cv_strokeWidthSize", DEFAULT_STROKE_WIDTH);
        mFillRadius = AttrUtils.getFloatFromAttr(attrs, "cv_fillRadius", DEFAULT_FILL_RADIUS);
        mTitleSubtitleSpace = AttrUtils.getFloatFromAttr(attrs, "cv_titleSubtitleSpace", DEFAULT_TITLE_SUBTITLE_SPACE);
        initPaint();

        weight = getWidth();
        mInnerRectF = new RectFloat(0, 0, weight + NUM_10, getHeight());
        addDrawTask(new DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                Arc arc = new Arc(0, NUM_360, false);
                canvas.drawArc(mInnerRectF, arc, mTitleTextPaint);
                float radius = (weight / NUM_2) * mFillRadius;
                canvas.drawCircle(new Circle(getWidth() / 2, getHeight() / 2,
                                radius + NUM_5F - mStrokePaint.getStrokeWidth()),
                        mBackgroundPaint);
                canvas.drawOval(mInnerRectF, mStrokePaint);
                if (mShowTitle) {
                    canvas.drawText(mFillPaint, mTitleText,
                            getWidth() / NUM_2 - NUM_25,
                            getHeight() / NUM_2);
                }

                if (mShowSubtitle) {
                    canvas.drawText(mSubTextPaint, mSubtitleText,
                            getWidth() / NUM_2,
                            getHeight() / NUM_2 + NUM_30
                    );
                }
            }
        });
        invalidate();

    }

    /**
     * getWeight
     *
     * @return intNUm
     */
    public int getWeight() {
        return weight;
    }

    /**
     * setWeight
     *
     * @param weight weight
     */
    public void setWeight(int weight) {
        this.weight = weight;
        mInnerRectF = new RectFloat(0, 0, weight, getHeight() - NUM_10);
        postLayout();
        invalidate();
    }

    public int getHeight() {
        return height;
    }

    /**
     * setHeight
     *
     * @param height height
     */
    public void setHeight(int height) {
        this.height = height;
        mInnerRectF = new RectFloat(0, 0, weight, height - NUM_10);
        postLayout();
        invalidate();
    }

    private void initPaint() {
        mTitleTextPaint = new Paint();
        mTitleTextPaint.setStyle(Paint.Style.FILLANDSTROKE_STYLE);
        mTitleTextPaint.setTextAlign(TextAlignment.CENTER);
        mTitleTextPaint.setMultipleLine(true);
        mTitleTextPaint.setColor(new Color(mTitleColor));
        mTitleTextPaint.setColor(Color.GRAY);
        mTitleTextPaint.setTextSize(mTitleSize);
        mTitleTextPaint.setAntiAlias(true);
        mSubTextPaint = new Paint();
        mSubTextPaint.setStyle(Paint.Style.FILLANDSTROKE_STYLE);
        mSubTextPaint.setTextAlign(TextAlignment.CENTER);
        mSubTextPaint.setMultipleLine(true);
        mSubTextPaint.setColor(new Color(mSubtitleColor));
        mSubTextPaint.setColor(Color.RED);
        mSubTextPaint.setTextSize(NUM_25);
        mSubTextPaint.setAntiAlias(true);
        mStrokePaint = new Paint();
        mStrokePaint.setStyle(Paint.Style.STROKE_STYLE);
        mStrokePaint.setColor(new Color(mStrokeColor));
        mStrokePaint.setStrokeWidth(mStrokeWidth);
        mStrokePaint.setAntiAlias(true);
        mBackgroundPaint = new Paint();
        mBackgroundPaint.setStyle(Paint.Style.FILL_STYLE);
        mBackgroundPaint.setColor(new Color(mBackgroundColor));
        mBackgroundPaint.setColor(new Color(Color.getIntColor("#5DB762")));
        mBackgroundPaint.setAntiAlias(true);
        mFillPaint = new Paint();
        mFillPaint.setStyle(Paint.Style.FILL_STYLE);
        mFillPaint.setColor(new Color(mFillColor));
        mFillPaint.setColor(Color.WHITE);
        mFillPaint.setAntiAlias(true);
        mFillPaint.setTextSize(NUM_25);
    }

    private void invalidateTextPaints() {
        mTitleTextPaint.setColor(new Color(mTitleColor));
        mSubTextPaint.setColor(new Color(mSubtitleColor));
        mTitleTextPaint.setTextSize(mTitleSize);
        mSubTextPaint.setTextSize(mSubtitleSize);
        invalidate();
    }

    private void invalidatePaints() {
        mBackgroundPaint.setColor(new Color(mBackgroundColor));
        mStrokePaint.setColor(new Color(mStrokeColor));
        mFillPaint.setColor(new Color(mFillColor));
        invalidate();
    }


    /**
     * Sets whether the view's title string will be shown.
     *
     * @param flag The boolean value.
     */
    public void setShowTitle(boolean flag) {
        this.mShowTitle = flag;
        invalidate();
    }

    /**
     * Sets whether the view's subtitle string will be shown.
     *
     * @param flag The boolean value.
     */
    public void setShowSubtitle(boolean flag) {
        this.mShowSubtitle = flag;
        invalidate();
    }

    /**
     * Gets the title string attribute value.
     *
     * @return The title string attribute value.
     */
    public String getTitleText() {
        return mTitleText;
    }

    /**
     * Sets the view's title string attribute value.
     *
     * @param title The example string attribute value to use.
     */
    public void setTitleText(String title) {
        mTitleText = title;
        invalidate();
    }

    /**
     * Gets the subtitle string attribute value.
     *
     * @return The subtitle string attribute value.
     */
    public String getSubtitleText() {
        return mSubtitleText;
    }

    /**
     * Sets the view's subtitle string attribute value.
     *
     * @param subtitle The example string attribute value to use.
     */
    public void setSubtitleText(String subtitle) {
        mSubtitleText = subtitle;
        invalidate();
    }

    /**
     * Gets the stroke color attribute value.
     *
     * @return The stroke color attribute value.
     */
    public int getStrokeColor() {
        return mStrokeColor;
    }

    /**
     * Gets the background color attribute value.
     *
     * @return The background color attribute value.
     */
    public int getBackgroundColor() {
        return mBackgroundColor;
    }

    /**
     * Gets the fill color attribute value.
     *
     * @return The fill color attribute value.
     */
    public int getFillColor() {
        return mStrokeColor;
    }

    /**
     * Sets the view's stroke color attribute value.
     *
     * @param strokeColor The stroke color attribute value to use.
     */
    public void setStrokeColor(int strokeColor) {
        mStrokeColor = strokeColor;
        invalidatePaints();
    }

    /**
     * Sets the view's background color attribute value.
     *
     * @param backgroundColor The background color attribute value to use.
     */
    public void setBackgroundColor(int backgroundColor) {
        mBackgroundColor = backgroundColor;
        invalidatePaints();
    }

    /**
     * Sets the view's stroke width attribute value.
     *
     * @param strokeWidth The stroke width attribute value to use.
     */
    public void setBackgroundColor(float strokeWidth) {
        mStrokeWidth = strokeWidth;
        invalidate();
    }

    /**
     * Sets the view's fill color attribute value.
     *
     * @param fillColor The fill color attribute value to use.
     */
    public void setFillColor(int fillColor) {
        mFillColor = fillColor;
        invalidatePaints();
    }

    /**
     * Gets the stroke width dimension attribute value.
     *
     * @return The stroke width dimension attribute value.
     */
    public float getStrokeWidth() {
        return mStrokeWidth;
    }


    /**
     * Gets the fill radius dimension attribute value.
     *
     * @return The fill radius dimension attribute value.
     */
    public float getFillRadius() {
        return mFillRadius;
    }

    /**
     * Sets the view's fill radius attribute value.
     *
     * @param fillRadius The fill radius attribute value to use.
     */
    public void setFillRadius(float fillRadius) {
        mFillRadius = fillRadius;
        invalidate();
    }

    /**
     * Gets the title size dimension attribute value.
     *
     * @return The title size dimension attribute value.
     */
    public float getTitleSize() {
        return mTitleSize;
    }

    /**
     * Sets the view's title size dimension attribute value.
     *
     * @param titleSize The title size dimension attribute value to use.
     */
    public void setTitleSize(int titleSize) {
        mTitleSize = titleSize;
        invalidateTextPaints();
    }

    /**
     * Gets the subtitle size dimension attribute value.
     *
     * @return The subtitle size dimension attribute value.
     */
    public float getSubtitleSize() {
        return mSubtitleSize;
    }

    /**
     * Sets the view's subtitle size dimension attribute value.
     *
     * @param subtitleSize The subtitle size dimension attribute value to use.
     */
    public void setSubtitleSize(int subtitleSize) {
        mSubtitleSize = subtitleSize;
        invalidateTextPaints();
    }

    /**
     * Gets the title text color attribute value.
     *
     * @return The text color attribute value.
     */
    public int getTitleColor() {
        return mTitleColor;
    }

    /**
     * Sets the view's title text color attribute value.
     *
     * @param titleColor The title text color attribute value to use.
     */
    public void setTitleColor(int titleColor) {
        mTitleColor = titleColor;
        invalidateTextPaints();
    }

    /**
     * Gets the subtitle text color attribute value.
     *
     * @return The text color attribute value.
     */
    public int getSubtitleColor() {
        return mSubtitleColor;
    }

    /**
     * Sets the view's subtitle text color attribute value.
     *
     * @param subtitleColor The subtitle text color attribute value to use.
     */
    public void setSubtitleColor(int subtitleColor) {
        mSubtitleColor = subtitleColor;
        invalidateTextPaints();
    }

    /**
     * Gets the title subtitle space attribute value.
     *
     * @return The title subtitle space attribute value.
     */
    public float getTitleSubtitleSpace() {
        return mTitleSubtitleSpace;
    }

    /**
     * Sets the view's title subtitle space attribute value.
     *
     * @param titleSubtitleSpace The space between title and subtitle attribute value to use.
     */
    public void setTitleSubtitleSpace(float titleSubtitleSpace) {
        this.mTitleSubtitleSpace = titleSubtitleSpace;
        invalidateTextPaints();
    }

}